﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using Kinect.Framework.Controller;
using System.Collections.ObjectModel;
using System.ComponentModel;
using Kinect.Framework.Lib;

namespace Kinect.Framework.Controls
{
    public class KinectWindow : Window, INotifyPropertyChanged
    {
        public KinectManipulationController controller { get; private set; }

        #region KinectPointers
        /// <summary>
        /// The KinectPointers Dependency
        /// </summary>
        public static readonly DependencyProperty KinectPointersProperty = DependencyProperty.RegisterAttached("KinectPointers", typeof(ObservableCollection<KinectPointer>), typeof(KinectWindow), new FrameworkPropertyMetadata(new ObservableCollection<KinectPointer>(), new PropertyChangedCallback(OnKinectPointersChanged)));
        /// <summary>
        /// The Header of your item
        /// </summary>
        public ObservableCollection<KinectPointer> KinectPointers
        {
            get { return (ObservableCollection<KinectPointer>)GetValue(KinectWindow.KinectPointersProperty); }
            set
            {
                SetValue(KinectWindow.KinectPointersProperty, value);
            }
        }
        /// <summary>
        /// Handles changes to the KinectPointers property.
        /// </summary>
        private static void OnKinectPointersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
        }
        #endregion

        public static KinectManipulationController GestureController(UIElement visual)
        {
            if (VisualTreeHelpers.FindVisualParent<KinectWindow>(visual) == null)
                return null;
            return VisualTreeHelpers.FindVisualParent<KinectWindow>(visual).controller;
        }
        public static KinectWindow CurrentWindow(UIElement visual)
        {
            return VisualTreeHelpers.FindVisualParent<KinectWindow>(visual);
        }

        static KinectWindow()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(KinectWindow), new FrameworkPropertyMetadata(typeof(KinectWindow)));
        }

        public KinectWindow()
        {
            controller = new KinectManipulationController();
            controller.KinectPointerCreated += new KinectManipulationController.KinectPointerCreatedEventHandler(OnKinectPointerCreated);
            controller.KinectPointerDestroyed += new KinectManipulationController.KinectPointerDestroyedEventHandler(OnKinectPointerDestroyed);
            controller.ManipulationDetected += new KinectManipulationController.ManipulationDetectedEventHandler(OnManipulationDetected);
            controller.ForceOneHandNavigation = false;
            SizeChanged += (s, e) =>
            {
                controller.ActualHeight = this.ActualHeight;
                controller.ActualWidth = this.ActualWidth;
            };
            Loaded += new RoutedEventHandler(OnLoaded);
            Closing += new System.ComponentModel.CancelEventHandler(OnClosing);

        }
        void OnKinectPointerDestroyed(object s, Framework.Lib.PayloadEventArgs<KinectPointer> e)
        {
            KinectPointers.Remove(e.Payload);
        }

        void OnKinectPointerCreated(object s, Framework.Lib.PayloadEventArgs<Framework.Controls.KinectPointer> e)
        {
            if (KinectPointers == null)
                KinectPointers = new ObservableCollection<KinectPointer>();
            KinectPointers.Add(e.Payload);
        }

        void OnLoaded(object sender, RoutedEventArgs e)
        {
            controller.Start();
        }

        void OnClosing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            controller.Stop();
        }

        void OnManipulationDetected(object s, PayloadEventArgs<KinectManipulationDelta> e)
        {
            var pointer = controller.Pointers.Where(p => p.Id == e.Payload.Id).FirstOrDefault();
            pointer.UpdateManipulatedElement(this);
        }

        #region INotifyPropertyChanged Members

        /// <summary>
        /// Issu de l'implémentation de l'interface INotifyPropertyChanged
        /// </summary>
        public virtual void OnPropertyChanged(string p)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(p));
            }
        }
        /// <summary>
        /// Issu de l'implémentation de l'interface INotifyPropertyChanged
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        public bool IsDesignTime
        {
            get
            {
                return (Application.Current == null) || (Application.Current.GetType() == typeof(Application));
            }
        }

        #endregion
    }
}
